#
#  Maps.py
#  TurnShip
#
#  Created by Pete Lord on 30/12/2008.
#  Copyright (c) 2008 __MyCompanyName__. All rights reserved.
#
import pygame, os, Options

class Tile():
    def __init__(self, x, y, cloud, smoke, texture_path, graphics):        
        self.x = x
        self.y = y
        self.cloud = cloud # do we have cloud here? DEFAULT: False
        self.smoke = smoke # do we have smoke here? DEFAULT: False
        # reference to the entities instance. Tiles don't need to access map for
        # anything else, but just need to access the graphics handler to load their textures.
        self.textures = graphics[texture_path]
        
class Map():
    def __setup__(self, entities):
        self.view = entities.view
        self.entities = entities
        temp = os.path.join('Data', 'Tiles')
        self.texture_list = [os.path.join(temp, 'Nothing'),
                             os.path.join(temp, 'Cloud'),
                            ]
        i = 0
        self.tiles = []
        for item in self.data:
            if i % self.width == 0:
                self.tiles.append([])
            self.tiles[-1].append(Tile(i % self.width, i / self.width, False, False, self.texture_list[item], self.entities.tile_graphics))
            i += 1
        self.update_surfaces()
    
    def update_surfaces(self):
        # Draw ground tiles. 
        # Optimization: Blit the ground to a surface on load once then blit that surface or a subsurface (based on player view) of that surface on tick. --- Done
        self.surfaces = []
        for zoom_level in (0, 1, 2):
            # Create a new surface of the correct width and height for the zoom level
            self.surfaces.append(pygame.Surface((Options.TILE_WIDTH[zoom_level] * 0.5 * (self.width + self.height),\
                                       Options.TILE_HEIGHT[zoom_level] * 0.5 * (self.width + self.height))))
            # Loop through each tile
            for j in range(self.height):
                for i in range(self.width):
                    # Calculate the screen (x, y)
                    x = (i - j + self.height - 1) * 0.5 * Options.TILE_WIDTH[zoom_level]
                    y = (i + j) * 0.5 * Options.TILE_HEIGHT[zoom_level]
                    # Draw the tile to surface
                    self.surfaces[-1].blit(self.tiles[j][i].textures[zoom_level], (x, y))
            self.surfaces[-1].convert()
                 
    def draw(self):
        self.view.screen.blit(self.surfaces[Options.ZOOM_LEVEL], (0, 0), self.view.rect)

    def map_location(self, pos):
        """ Accepts absolute (x, y) and returns map (x, y) """
        x, y = pos
        # Take screen offset out of (x, y)
        x, y = x + self.view.rect.x, y + self.view.rect.y
        
        # Account for map (0, 0) not centred at (0, 0) on screen
        x, y = x - self.height * Options.TILE_WIDTH[Options.ZOOM_LEVEL] / 2, y - Options.TILE_HEIGHT[Options.ZOOM_LEVEL] / 2
        
        # Convert screen (x, y) to map (x, y)
        # Note: it does the calculation as floats for accuracy,
        # then adds 0.5 to counter the rounding up/down issue
        map_x = int(float(y) / Options.TILE_HEIGHT[Options.ZOOM_LEVEL] + float(x) / Options.TILE_WIDTH[Options.ZOOM_LEVEL] + 0.5)
        map_y = int(float(y) / Options.TILE_HEIGHT[Options.ZOOM_LEVEL] - float(x) / Options.TILE_WIDTH[Options.ZOOM_LEVEL] + 0.5)
        return map_x, map_y
    
    def get_at_xy(self, pos):
        """ Accepts map (x, y) and returns object currently there.
        
        If no object there, return None"""
        for player in self.entities.players.values():
            for ship in player.ships.values():
                if (ship.x, ship.y) == pos:
                    return ship
        return None
        
    def get_at_screen_xy(self, pos):
        """ Accepts screen (x, y) and returns object currently there.
        
        If no object there, return None"""
        return self.get_at_xy(self.map_location(pos))
